import os, sys
import pygame

from pygame import constants
from pygame.locals import *
from Box2D import *




INFINITY = 1e1000
BLACK    = 0x0
THISDIR = os.path.dirname( __file__ )

DISPLAY_SIZE = 800, 600

LEFT = 0
RIGHT = 1

FIRST = 0
SECOND = 1

STATIC = 0
DINAMYC = 1

METAL = 1


# Initialize and setup screen
pygame.init()
    
screen = pygame.display.set_mode(DISPLAY_SIZE)

from goal import *
from ball import *
from block import *
from triangle import *
from slopes import *


class StopDemoException( Exception ): pass

def check_exit_event( event ):
    if event.type == pygame.KEYDOWN:
        # K_ESCAPE = Right softkey
        if event.type == pygame.KEYDOWN \
        and event.key == constants.K_ESCAPE:
            raise StopDemoException( "User exited" )
    elif event.type == pygame.QUIT:
        raise StopDemoException( "User exited" )
    return None

def check_key_event( event ):
    if event.type == pygame.KEYDOWN:
        
        if event.type == pygame.KEYDOWN \
        and event.key == constants.K_ESCAPE:
            return False
        else:
            return True

    return False

class NewtonWorld:
    targetFPS = 40
    timeStep  = 1000 / targetFPS
    iterations = 5
    bodies = []
    count = 0
    worldAABB = None
    world     = None
    groundBodyDef = None
    groundShapeDef = None



    def __init__(self):

        
        # Step 1: Create Physics World Boundaries
        self.worldAABB = b2AABB()
        self.worldAABB.lowerBound = b2Vec2(-0.0, -0.0);
        self.worldAABB.upperBound = b2Vec2(80.0, 60.0);

        # Step 2: Create Physics World with Gravity
        gravity = b2Vec2(0.0, 100.0);
        doSleep = True
        self.world = b2World(self.worldAABB, gravity, doSleep);

        def make_rect(x,y, w, h):
            self.groundBodyDef = b2BodyDef();
            self.groundBodyDef.position = b2Vec2(x,y);
            self.groundBody = self.world.CreateBody(self.groundBodyDef);

            self.groundShapeDef = b2PolygonDef();
            self.groundShapeDef.SetAsBox(w, h);
            self.groundBody.CreateShape(self.groundShapeDef);

        # Make world borders
        # Ground
        make_rect( 0.0, 60.0,  80,  0.05 )
        # Top
        make_rect( 0.0,  0.0,  80,  0.05 )
        # Left
        make_rect( 0.0,  0.0, 0.1, 60.0 )
        # Right
        make_rect( 80.0, 0.0, 0.1, 60.0 )



    def addBullets(self):
        # Create Dynamic Body
        bodyDef = b2BodyDef();
        bodyDef.isBullet = True
        bodyDef.position = ( 0.2+self.count * 5.8, 0.2+self.count*0.1);
        #bodyDef.position = ( 10, 1);
        b = self.world.CreateBody(bodyDef);
        self.bodies.append( b )
    
        # Create Shape with Properties
        circle = b2CircleDef()
        #circle.radius      = 0.2 + 0.1 * self.count
        circle.radius      =  0.4    
        circle.density     = 10
        circle.restitution = 1
        circle.mass = 0.1 + 0.1 * self.count

        # Assign shape to Body
        self.bodies[self.count].CreateShape(circle);
        self.bodies[self.count].SetMassFromShapes();

        # Increase Counter
        self.count += 1;

    def create_scenario(self):
        objects = []

    ##Estaticos

        ##Pared Conetedora
        new_obj = Block(self.world, 16, 58, STATIC, metal=METAL)
        objects.append(new_obj) 
        new_obj = Block(self.world, 16, 53.4, STATIC, metal=METAL)
        objects.append(new_obj)
        new_obj = Block(self.world, 16, 49.0, STATIC, metal=METAL)
        objects.append(new_obj)            

        ##Estructura de rampas
        ##1
        new_obj = Slope(self.world, 6, 15, LEFT, SECOND)
        objects.append(new_obj)

        new_obj = Slope(self.world, 6+4.4, 15, LEFT, FIRST)
        objects.append(new_obj)


        ##2
        new_obj = Block(self.world, 20+4.3, 26, STATIC)
        objects.append(new_obj)

        new_obj = Slope(self.world, 20+4.3, 26-4.5, RIGHT, FIRST)
        objects.append(new_obj)

        new_obj = Slope(self.world, 20, 26, RIGHT, SECOND)
        objects.append(new_obj)

        new_obj = Slope(self.world, 20-4.3, 26, RIGHT, FIRST)
        objects.append(new_obj)


        ##3
        new_obj = Slope(self.world, 6, 33, LEFT, SECOND)
        objects.append(new_obj)

        new_obj = Slope(self.world, 6+4.4, 33, LEFT, FIRST)
        objects.append(new_obj)

        ##4
        new_obj = Block(self.world, 20+4.3, 42, STATIC)
        objects.append(new_obj)

        new_obj = Slope(self.world, 20+4.3, 42-4.5, RIGHT, FIRST)
        objects.append(new_obj)

        new_obj = Slope(self.world, 20, 42, RIGHT, SECOND)
        objects.append(new_obj)

        new_obj = Slope(self.world, 20-4.3, 42, RIGHT, FIRST)
        objects.append(new_obj)

        ##Rebotadores
        new_obj = Ball(self.world, 45, 20, STATIC)
        objects.append(new_obj)

        new_obj = Ball(self.world, 65, 20, STATIC)
        objects.append(new_obj)

        new_obj = Ball(self.world, 55, 40, STATIC)
        objects.append(new_obj)

        ##Triangulos
        new_obj = Triangle(self.world, 79, 30, angl=90)
        objects.append(new_obj)

        new_obj = Triangle(self.world, 35, 30, angl=-90)
        objects.append(new_obj)

        ##Block Joker
        new_obj = Block(self.world, 40, 47, STATIC, metal=JOKER)
        objects.append(new_obj)

        new_obj = Block(self.world, 70, 47, STATIC, metal=JOKER)
        objects.append(new_obj)

    ##Dinamicos
        ##Bolas

        new_obj = Ball(self.world, 45, 10)
        objects.append(new_obj)

        new_obj = Ball(self.world, 65, 10)
        objects.append(new_obj)

        new_obj = Ball(self.world, 55, 10)
        objects.append(new_obj)


        new_obj = Ball(self.world, 45+5, 10)
        objects.append(new_obj)

        new_obj = Ball(self.world, 65+5, 10)
        objects.append(new_obj)

        new_obj = Ball(self.world, 55+5, 10)
        objects.append(new_obj)

        #new_obj = Ball(world, 24, 5)
        #objects.append(new_obj)
        
        new_obj = Block(self.world, 7, 5, DINAMYC)
        objects.append(new_obj)

        new_obj = Block(self.world, 22, 9, DINAMYC)
        objects.append(new_obj)

        new_obj = Block(self.world, 73, 8, DINAMYC)
        objects.append(new_obj)
       # new_obj = Goal(world, 50, 50)
       # objects.append(new_obj)
        
        return objects

def run_world():


    fondo_srf = pygame.image.load('images/UnderwhereWallpaper.png').convert()    

    world = NewtonWorld()

    for x in xrange(15):
        world.addBullets()

  
    clock  = pygame.time.Clock()
    tics   = pygame.time.get_ticks()
    colors = [ 0xFF0000, 0x00FF00, 0xFF00FF, 0x00FF00, 0xFFFF00, 0x00FFFF ]

    elements = []

    elements =  world.create_scenario()

    from pygame import draw
    import random

    while 1:

        clock.tick(30)
        for event in pygame.event.get():
            check_exit_event( event )
            

        # Clear screen
        screen.fill(BLACK)

        screen.blit(fondo_srf, (0, 0))

        velocityIterations = 10
        positionIterations = 8

        timeStep = 1. / 60.
        world.world.SetWarmStarting(True)
    	world.world.SetContinuousPhysics(True)
        world.world.Step(timeStep, 10, positionIterations)
        world.world.Validate()

        i = 0
        for b in world.bodies:
            x, y = b.position.tuple()
            r = b.GetShapeList()[0].radius

            draw.circle( screen, colors[ i % len(colors)], ((x)*10, (y) * 10), r * 10, 0 )

            for obj in elements:
                obj.draw(screen)
    
                #for event_k in pygame.event.get():
                 #   print 'event key'
                  #  if (check_key_event( event_k )and (type(obj) is (Block or Ball))):
                   #     print 'block ball'
                    #    if obj.isAllowSleep :
                     #       print 'delete'
                      #      elements.remove(obj)
                       #     obj.destroy()
        
                if obj.sleeping() and type(obj) is Block:
                   
                    x=random.randint(5,75)
                    y=random.randint(1,10)
                    
                    if obj.isAllowSleep :
                        elements.remove(obj)
                        obj.destroy()
                 
                    for a in range (2, random.randint(2,8)):
                        new_obj = Block(world.world, random.randint(5,75), random.randint(1,10), DINAMYC)
                        elements.append(new_obj)
                        

                    for b in range (1, random.randint(1,7)):
                        new_obj = [Block,Ball][random.randint(0,1)](world.world, 
                        random.randint(5,75), random.randint(1,10), dinamyc=DINAMYC)
                        elements.append(new_obj)

            i += 1
            
        
        pygame.display.flip()
        clock.tick(30)

        tics = pygame.time.get_ticks()


#if __name__ == '__main__':
 #   try:
  #      main()
   # except StopDemoException:
    #    pass
